#include "p18cxxx.h"
#include "GenericTypeDefs.h"
#include <stdio.h>
#include "io_cfg.h"
#include "userLib.h"
#include "lib_usb_cdc.h"
#include "my_main.h"

#pragma config PLLDIV   = 2         // 8 MHz crystal
#pragma config CPUDIV   = OSC1_PLL2   
#pragma config USBDIV   = 2         // Clock source from 96MHz PLL/2
#pragma config FOSC     = HSPLL_HS
#pragma config FCMEN    = OFF
#pragma config IESO     = OFF
#pragma config PWRT     = OFF
#pragma config BOR      = ON
#pragma config BORV     = 3
#pragma config VREGEN   = ON      //USB Voltage Regulator
#pragma config WDT      = OFF
#pragma config WDTPS    = 32768
#pragma config MCLRE    = ON
#pragma config LPT1OSC  = OFF
#pragma config PBADEN   = OFF
#pragma config STVREN   = ON
#pragma config LVP      = OFF
#pragma config XINST    = OFF       // Extended Instruction Set
#pragma config CP0      = OFF
#pragma config CP1      = OFF
#pragma config CPB      = OFF
#pragma config WRT0     = OFF
#pragma config WRT1     = OFF
#pragma config WRTB     = OFF       // Boot Block Write Protection
#pragma config WRTC     = OFF
#pragma config EBTR0    = OFF
#pragma config EBTR1    = OFF
#pragma config EBTRB    = OFF

#define PROGRAMMABLE_WITH_USB_HID_BOOTLOADER

void YourHighPriorityISRCode();
void YourLowPriorityISRCode();


/** VECTOR REMAPPING ***********************************************/
//On PIC18 devices, addresses 0x00, 0x08, and 0x18 are used for
//the reset, high priority interrupt, and low priority interrupt
//vectors.  However, the current Microchip USB bootloader 
//examples are intended to occupy addresses 0x00-0x7FF or
//0x00-0xFFF depending on which bootloader is used.  Therefore,
//the bootloader code remaps these vectors to new locations
//as indicated below.  This remapping is only necessary if you
//wish to program the hex file generated from this project with
//the USB bootloader.  If no bootloader is used, edit the
//usb_config.h file and comment out the following defines:
//#define PROGRAMMABLE_WITH_USB_HID_BOOTLOADER
//#define PROGRAMMABLE_WITH_USB_LEGACY_CUSTOM_CLASS_BOOTLOADER

#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
	#define REMAPPED_RESET_VECTOR_ADDRESS			0x1000
	#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS	0x1008
	#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS	0x1018
#else	
	#define REMAPPED_RESET_VECTOR_ADDRESS			0x00
	#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS	0x08
	#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS	0x18
#endif


extern void _startup (void);        // See c018i.c in your C18 compiler dir
#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
void _reset (void)
{
    _asm goto _startup _endasm
}

#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
void Remapped_High_ISR (void)
{
     _asm goto YourHighPriorityISRCode _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
void Remapped_Low_ISR (void)
{
     _asm goto YourLowPriorityISRCode _endasm
}

#pragma code HIGH_INTERRUPT_VECTOR = 0x08
void High_ISR (void)
{
     _asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm
}
#pragma code LOW_INTERRUPT_VECTOR = 0x18
void Low_ISR (void)
{
     _asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm
}

#pragma code

#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{
#ifdef USE_FREECLK  
	freeclk_interrupt();      		// executed to service freeclk interrupt
#endif
#ifdef USE_USB
	lib_usb_cdc_process_interrupt();// usb sertvice
#endif
}

#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
	
}	

//
// standard initialization routine 
//

void initialize(void)				// setup and enable the hardware to be used
{
   picInit(SYSCLK, PBCLK);   		// basic initialization

   A2D_init(3);						// set AN0-AN3 to be analog and the rest digital
   LED_INIT = 0;         			// specify LEDs for output

   // USB
   #ifdef USE_USB
   lib_usb_cdc_open();
   INTCONbits.GIE = 1;               // Global Enable Interrupt
   #endif
   
   #ifdef USE_UART
   // UART for stdin, stdout access
   // the last param spbrg determines the baud rate = FOSC / (16 * (spbrg + 1))
   // For 20Mhz clk: 10=115200, 21=57600, 32=38400, 64=19200, 129=9600
   // For 40Mhz clk: 10=230400, 21=115200, 42=57600, 32=38400, 64=38400, 129=19200, 259=9600
   
   OpenUSART( USART_TX_INT_OFF  &
              USART_RX_INT_OFF  &
              USART_ASYNCH_MODE &
              USART_EIGHT_BIT   &
              USART_CONT_RX     &
              USART_BRGH_HIGH,
              12             );      // sets for 115200 BPS @ 20MHz clk, 230400 @ 40MHz
   #endif
	
   //  Vex ultrasonic rangefinder
   //  All these require timer T2: must also enable delayT2_init() below
   //  Up to 3 devices can be controlled using different RC or RD pins

   #ifdef USE_VEX_ULTRASONIC1
   readVexUltraSonic1_init();   // #1 uses pins RC0, RC1
   #endif
   
   #ifdef USE_VEX_ULTRASONIC2
   readVexUltraSonic2_init();   // #2 uses pins RD0, RD1
   #endif
   
   #ifdef USE_VEX_ULTRASONIC3
   readVexUltraSonic3_init();   // #3 uses pins RD2, RD3
   #endif

   // I2C peipheral for output D/A, eg for Vex motors via MAX517 and 555 timer chips
   
   #ifdef USE_I2C
   OpenI2C(MASTER, SLEW_ON);         // enables I2C device
//   Set 400KHz I2C clk by setting SSPADD = (FOSC / 1,600,000) - 1 
//   SSPADD = 12;                  // 400KHz I2C Clk for 20MHz FOSC, see Data Sheet SSPADD sec
//   SSPADD = 24;                  // 400KHz I2C Clk for 40MHz FOSC, see Data Sheet SSPADD sec
   #define SSPADD ((PBCLK/1600000)-1)
   #endif
   
   // Freerunning clock uses timer T0, including interrupt
    
   #ifdef USE_FREECLK  
   INTCONbits.GIE = 1;             // Global Enable Interrupt
   freeclk_init();
   #endif
   
   // Timers for delayTx_ms(ms) and delayTx_us(us)
   
   #ifdef USE_DELAY_TIMER0
   delayT0_init();                 // enables timer 0 for delays
   #endif
   
   #ifdef USE_DELAY_TIMER1
   delayT1_init();                 // enables timer 1 for delays
   #endif
   
   #ifdef USE_DELAY_TIMER2
   delayT2_init();                 // enables timer 2 for delays
   #endif
   
   #ifdef USE_DELAY_TIMER3
   delayT3_init();                 // enables timer 3 for delays
   #endif
   
}
   

void main(void)
{	
	initialize();				// enable needed hardware; configure as desired above
	
	my_main();					// call user main code
	
}

